package besta.moon.engine.selector.multioper;

import besta.moon.engine.RowSource;
import besta.moon.sql.Expression;
import besta.moon.sql.expression.Expressions;

public class Where extends RowSource {

    final private RowSource rowSource;
    final private Expression where;
    private int row = 0;
    private boolean isCurrentRow;

    public Where(RowSource rowSource, Expression where) {
        this.rowSource = rowSource;
        this.where = where;
    }

    public RowSource getFrom() {
        return rowSource;
    }

    final private boolean isValidRow() throws Exception {
        return where == null || rowSource.rowInserted() || where.getBoolean();
    }

    @Override
    public final boolean isScrollable() {
        return rowSource.isScrollable();
    }

    @Override
    public final boolean isBeforeFirst() {
        return row == 0;
    }

    @Override
    public final boolean isFirst() {
        return row == 1 && isCurrentRow;
    }

    @Override
    public final boolean isLast() throws Exception {
        if (!isCurrentRow) {
            return false;
        }
        long rowPos = rowSource.getRowPosition();
        boolean isNext = next();
        rowSource.setRowPosition(rowPos);
        return !isNext;
    }

    @Override
    public final boolean isAfterLast() {
        return row > 0 && !isCurrentRow;
    }

    @Override
    public final void beforeFirst() throws Exception {
        rowSource.beforeFirst();
        row = 0;
    }

    @Override
    public final boolean first() throws Exception {
        isCurrentRow = rowSource.first();
        while (isCurrentRow && !isValidRow()) {
            isCurrentRow = rowSource.next();
        }
        row = 1;
        return isCurrentRow;
    }

    @Override
    public final boolean previous() throws Exception {
        boolean oldIsCurrentRow = isCurrentRow;
        do {
            isCurrentRow = rowSource.previous();
        } while (isCurrentRow && !isValidRow());
        if (oldIsCurrentRow || isCurrentRow) {
            row--;
        }
        return isCurrentRow;
    }

    @Override
    public final boolean next() throws Exception {
        boolean oldIsCurrentRow = isCurrentRow;
        do {
            isCurrentRow = rowSource.next();
        } while (isCurrentRow && !isValidRow());
        if (oldIsCurrentRow || isCurrentRow) {
            row++;
        }
        return isCurrentRow;
    }

    @Override
    public final boolean last() throws Exception {
        while (next()) {
        }
        return previous();
    }

    @Override
    public final void afterLast() throws Exception {
        while (next()) {
        }
    }

    @Override
    public final int getRow() throws Exception {
        return isCurrentRow ? row : 0;
    }

    @Override
    public final long getRowPosition() {
        return rowSource.getRowPosition();
    }

    @Override
    public final void setRowPosition(long rowPosition) throws Exception {
        rowSource.setRowPosition(rowPosition);
    }

    @Override
    public final void nullRow() {
        rowSource.nullRow();
        row = 0;
    }

    @Override
    public final void noRow() {
        rowSource.noRow();
        row = 0;
    }

    @Override
    public final boolean rowInserted() {
        return rowSource.rowInserted();
    }

    @Override
    public final boolean rowDeleted() {
        return rowSource.rowDeleted();
    }

    @Override
    public final void execute() throws Exception {
        rowSource.execute();
    }

    @Override
    public boolean isExpressionsFromThisRowSource(Expressions columns) {
        return rowSource.isExpressionsFromThisRowSource(columns);
    }
}
